package model;

import java.util.Arrays;

import org.mybeans.dao.DAOException;
import org.mybeans.factory.BeanFactory;
import org.mybeans.factory.BeanFactoryException;
import org.mybeans.factory.BeanTable;
import org.mybeans.factory.DuplicateKeyException;
import org.mybeans.factory.MatchArg;
import org.mybeans.factory.RollbackException;
import org.mybeans.factory.Transaction;

import databeans.Fund;

/*
 * 
 * made by alesmana@andrew.cmu.edu
 * class for 15-600 homework 9
 * 
 * UserDAO
 * 
 */

public class FundDAO {
    private BeanFactory<Fund> factory;

    
    public FundDAO() throws DAOException {
        try {
            // Get a BeanTable so we can create the "employee" table
            BeanTable<Fund> fundTable = BeanTable.getInstance(Fund.class, "cfa_fund");

            if (!fundTable.exists()) {
                fundTable.create("fundID"); //Fund ID will be the PK for the table

                fundTable.setIdleConnectionCleanup(true); //see below explanation
                // Get a BeanFactory which the actions will use to read and
                // write rows of the "user" table
                factory = fundTable.getFactory();
                
                //initially populate with sample data
                bootData();
            } else {
                // Long running web apps need to clean up idle database connections.
                // So we can tell each BeanTable to clean them up. (You would only notice
                // a problem after leaving your web app running for several hours.)
                fundTable.setIdleConnectionCleanup(true);

                // Get a BeanFactory which the actions will use to read and
                // write rows of the "user" table
                factory = fundTable.getFactory();
            }

        } catch (BeanFactoryException e) {
            throw new DAOException(e);
        }
    }
   

    private void bootData() throws DAOException {
        
        
        Fund fundTest1 = new Fund();
        fundTest1.setName("Wrestling Index");
        fundTest1.setSymbol("WTF");
        create(fundTest1);
        
        Fund fundTest2 = new Fund(); 
        fundTest2.setName("Asset Allocation");
        fundTest2.setSymbol("VAAPX");

        create(fundTest2);
        
        fundTest1.setName("Spam Haus");
        fundTest1.setSymbol("SPAM");
        
        create(fundTest1);
        
        fundTest2.setName("Billy Gates");
        fundTest2.setSymbol("BIG");
        
        create(fundTest2);
    }

    public void create(Fund fund) throws DAOException {
        try {
            Transaction.begin();
            Fund dbFund = factory.create();
            fund.setFundID(dbFund.getFundID());
            factory.copyInto(fund, dbFund);
            Transaction.commit();
        } catch (DuplicateKeyException e) {
            throw new DAOException("A fund with ID " + fund.getFundID() + " has already exists");
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    
    //by alvin
    public int createReturnID(Fund fund) throws DAOException {
        try {
            Transaction.begin();
            Fund dbFund = factory.create();
            int fID = dbFund.getFundID();
            fund.setFundID(fID);
            factory.copyInto(fund, dbFund);
            Transaction.commit();
            return fID;
        } catch (DuplicateKeyException e) {
            throw new DAOException("A fund with ID " + fund.getFundID() + " has already exists");
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    
    /*
    public void delete(int id) throws DAOException {
        try {
            Transaction.begin();
            Fund f = factory.lookup(id);

            if (f == null) {
                throw new DAOException("Fund does not exist: id=" + id);
            }

            factory.delete(id);
            Transaction.commit();
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    */

    public Fund lookup(int id) throws DAOException {
        try {
            return factory.lookup(id);
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }
    
    
    public Fund lookup(String symbol) throws DAOException {
        try {            
            Fund[] fundList = getFunds();         
            int customerID = -1;          
            for (int i = 0; i < fundList.length; i++){
                if (fundList[i].getSymbol().equals(symbol)){
                    customerID = fundList[i].getFundID();
                }
            }
            return factory.lookup(customerID);          
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }
    

    protected BeanFactory<Fund> getFactory() {
        return factory;
    }

    public Fund[] getFunds() throws DAOException {
        try {
            Fund[] funds = factory.match();
            Arrays.sort(funds); // we want them to sort based on symbol
            return funds;
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }
    
    public int getNoOfFunds() throws DAOException {
        try {
            Fund[] funds = factory.match();
            return funds.length;
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }

    public boolean checkDuplicates(Fund f) throws DAOException {
        boolean gotDuplicates = false;
        try {
            Fund[] list = factory.match(MatchArg.equals("name", f.getName()), MatchArg.equals("symbol", f.getSymbol()));
            if (list.length != 0) {
                gotDuplicates = true;
            }
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
        return gotDuplicates;
    }

    public void update(Fund fund) throws DAOException {
        try {
            Transaction.begin();
            int id = fund.getFundID();
            Fund dbFund = factory.lookup(id);
        
            if (dbFund == null) {
                throw new DAOException("Fund does not exist id= " + id);
            }
            
            dbFund.setName(fund.getName());
            dbFund.setSymbol(fund.getSymbol());
        
            Transaction.commit();
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }

}
